﻿using System;
using AntJob.Data;
using AntJob.Extensions;
using NewLife.Data;
using XCode.DataAccessLayer;

namespace AntJob
{
    /// <summary>SQL语句处理器，定时执行SQL语句</summary>
    /// <remarks>
    /// 应用型处理器，可直接使用
    /// </remarks>
    public class SqlHandler : Handler
    {
        #region 构造
        /// <summary>实例化</summary>
        public SqlHandler()
        {
            //Mode = JobModes.Sql;

            var job = Job;
            job.BatchSize = 8;
        }
        #endregion

        /// <summary>执行</summary>
        /// <param name="ctx"></param>
        /// <returns></returns>
        protected override Int32 Execute(JobContext ctx)
        {
            //var sqls = ctx.Task.Data as String;
            var sqls = Job.Data;
            sqls = TemplateHelper.Build(sqls, ctx.Task.Start, ctx.Task.End);
            // 向调度中心返回解析后的Sql语句
            ctx.Remark = sqls;

            var sections = SqlSection.ParseAll(sqls);
            if (sections.Length == 0) return -1;

            var rs = ExecuteSql(sections, ctx, (section, dt) => SqlMessage.ProduceMessage(dt, ctx));

            return rs;
        }

        /// <summary>执行Sql集合</summary>
        /// <param name="sections"></param>
        /// <param name="ctx"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        public static Int32 ExecuteSql(SqlSection[] sections, JobContext ctx, Action<SqlSection, DbTable> callback = null)
        {
            if (sections == null || sections.Length == 0) return -1;

            var rs = 0;
            ctx.Total = 0;

            // 打开事务
            foreach (var item in sections)
            {
                if (item.Action != SqlActions.Query) DAL.Create(item.ConnName).BeginTransaction();
            }
            try
            {
                // 按顺序执行处理Sql语句
                DbTable dt = null;
                foreach (var section in sections)
                {
                    switch (section.Action)
                    {
                        case SqlActions.Query:
                            dt = section.Query();
                            if (dt != null) ctx.Total += dt.Rows.Count;

                            // 处理生产消息
                            callback?.Invoke(section, dt);

                            break;
                        case SqlActions.Execute:
                            rs += section.Execute();
                            break;
                        case SqlActions.Insert:
                            if (dt.Rows.Count > 0) rs += section.BatchInsert(dt);
                            break;
                        default:
                            break;
                    }
                }

                // 提交事务
                foreach (var item in sections)
                {
                    if (item.Action != SqlActions.Query) DAL.Create(item.ConnName).Commit();
                }
            }
            catch
            {
                // 回滚事务
                foreach (var item in sections)
                {
                    if (item.Action != SqlActions.Query) DAL.Create(item.ConnName).Rollback();
                }

                throw;
            }

            return rs;
        }
    }
}